package org.hcyspartnoc.luoxin.utils;

import com.alibaba.fastjson2.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import okhttp3.*;
import org.hcyspartnoc.luoxin.common.core.configuration.ContrapsychConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.*;
import java.util.*;

@Component
public class MultimediaUtils {
    public static MediaType JSON_FORMAT = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType MEDIA_TYPE_WAV = MediaType.parse("audio/wav");
    private static final Logger logger = LoggerFactory.getLogger(MultimediaUtils.class);
    private static ContrapsychConfiguration contrapsychConfiguration;

    @Resource
    public void setContrapsychConfiguration(ContrapsychConfiguration contrapsychConfiguration) {
        MultimediaUtils.contrapsychConfiguration = contrapsychConfiguration;
    }

    // tts-> 通过text转base64音频
    public static String textToWavBase64(final String text, String filePath, String character) {
        if (text.isEmpty() || character.isEmpty())
            return null;
        // 调用tts模块生成wav
        // 构造请求数据
        Map<String, Object> data = new HashMap<>();
        data.put("text", text);
        data.put("character", character);
        data.put("speed", contrapsychConfiguration.getTts().getSpeed());
        data.put("format", contrapsychConfiguration.getTts().getFormat());
        // 创建MediaType和RequestBody
        RequestBody body = RequestBody.create(JSON.toJSONString(data), JSON_FORMAT);
        // 发送POST请求
        Request request = new Request.Builder()
                .url(contrapsychConfiguration.getTts().getUrl())
                .post(body)
                .build();
        OkHttpClient client = new OkHttpClient();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) return null;
            else {
                if (response.body() != null) {
                    byte[] contentBytes = response.body().bytes();
                    // 将音频写入文件
                    try (FileOutputStream fos = new FileOutputStream(filePath)) {
                        fos.write(contentBytes);
                    } catch (Exception e) {
                        return null;
                    }
                    // 将wav转成base64编码
                    return Base64.getEncoder().encodeToString(contentBytes);
                }
            }
        } catch (Exception e) {
            return null;
        }
        return null;
    }

    @Data
    private static class SttRes {
        private String transcript;
    }

    public static String base64ToText(final String base64) {
        if (base64.isEmpty())
            return null;
        try {
            // 将base64暂存为临时wav文件
            File tempFilesDir = new File(contrapsychConfiguration.getTempFilesDir());
            if (!tempFilesDir.exists())
                tempFilesDir.mkdirs();
            UUID uuid = UUID.randomUUID();
            String filePath = contrapsychConfiguration.getTempFilesDir() + uuid + ".wav";
            File audioFile = new File(filePath);
            byte[] decodedBytes = Base64.getDecoder().decode(base64);
            try (FileOutputStream fos = new FileOutputStream(audioFile)) {
                fos.write(decodedBytes);
            } catch (Exception e) {
                logger.error("写入音频文件时出错: {}", e.getMessage());
                return null;
            }
            RequestBody fileBody = RequestBody.create(decodedBytes, MEDIA_TYPE_WAV);
            RequestBody formBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("file", audioFile.getName(), fileBody)
                    .addFormDataPart("model", contrapsychConfiguration.getStt().getModel())
                    .build();
            Request request = new Request.Builder()
                    .url(contrapsychConfiguration.getStt().getUrl())
                    .post(formBody)
                    .addHeader("Authorization", contrapsychConfiguration.getStt().getAuthorization())
                    .build();
            OkHttpClient client = new OkHttpClient();
            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) return null;
                else {
                    if (response.body() != null) {
                        String resData = response.body().string();
                        return JSON.parseObject(resData, SttRes.class).getTranscript();
                    }
                }
            } catch (Exception e) {
                return null;
            } finally {
                if (audioFile.exists())
                    audioFile.delete();
            }
        } catch (Exception ignore) {
            return null;
        }
        return null;
    }


    @Data
    @Accessors(chain = true)
    public static class ChatReqBody {
        private String model;
        private Double temperature;
        private Integer max_new_tokens;
        private Double top_p;
        private Boolean stream;
        private ArrayList<Message> messages;

        @Data
        @Accessors(chain = true)
        @AllArgsConstructor
        public static class Message {
            private String role;
            private String content;
        }

        public static ChatReqBody getBaseResBody() {
            ChatReqBody chatReqBody = new ChatReqBody();
            chatReqBody.setModel(contrapsychConfiguration.getChat().getModel())
                    .setTemperature(contrapsychConfiguration.getChat().getTemperature())
                    .setStream(contrapsychConfiguration.getChat().getStream())
                    .setTop_p(contrapsychConfiguration.getChat().getTopP())
                    .setMax_new_tokens(contrapsychConfiguration.getChat().getMaxNewTokens());
            return chatReqBody;
        }
    }

    public static String getChatAnswer(ChatReqBody chatReqBody) {
        // 创建MediaType和RequestBody
        RequestBody body = RequestBody.create(JSON.toJSONString(chatReqBody), JSON_FORMAT);
        // 发送POST请求
        Request request = new Request.Builder()
                .url(contrapsychConfiguration.getChat().getUrl())
                .post(body)
                .build();
        OkHttpClient client = new OkHttpClient();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) return "";
            else {
                if (response.body() != null) {
                    // 返回回答
                    System.out.println("res:" + response.body());
                    return response.body().string();
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return "";
        }
        return "";
    }

    public static String generateNote(ChatReqBody chatReqBody) {
        HashMap<String, ArrayList<ChatReqBody.Message>> reqP = new HashMap<>();
        reqP.put("history", chatReqBody.getMessages());
        RequestBody body = RequestBody.create(JSON.toJSONString(reqP), JSON_FORMAT);
        Request request = new Request.Builder()
                .url(contrapsychConfiguration.getNote().getUrl())
                .post(body)
                .build();
        OkHttpClient client = new OkHttpClient();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) return "";
            else {
                if (response.body() != null) {
                    // 返回回答
                    String res = response.body().string();
                    return JSON.parseObject(res).getString("note");
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return "";
        }
        return "";
    }

    public static String synthesizeAudio(String wavPath1, String wavPath2) {
        try {
            // 读取第一个音频文件
            AudioInputStream audioInputStream1 = AudioSystem.getAudioInputStream(new File(wavPath1));
            ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
            AudioSystem.write(audioInputStream1, AudioFileFormat.Type.WAVE, baos1);

            // 读取第二个音频文件
            AudioInputStream audioInputStream2 = AudioSystem.getAudioInputStream(new File(wavPath2));
            ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
            AudioSystem.write(audioInputStream2, AudioFileFormat.Type.WAVE, baos2);

            // 合并两个音频流
            byte[] audioBytes1 = baos1.toByteArray();
            byte[] audioBytes2 = baos2.toByteArray();
            byte[] combinedAudioBytes = new byte[audioBytes1.length + audioBytes2.length];
            System.arraycopy(audioBytes1, 0, combinedAudioBytes, 0, audioBytes1.length);
            System.arraycopy(audioBytes2, 0, combinedAudioBytes, audioBytes1.length, audioBytes2.length);

            // 创建新的音频流
            AudioInputStream combinedAudioInputStream = new AudioInputStream(
                    new ByteArrayInputStream(combinedAudioBytes),
                    audioInputStream1.getFormat(),
                    audioBytes1.length + audioBytes2.length);

            // 保存合并后的音频文件
            UUID uuid = UUID.randomUUID();
            String filePath = contrapsychConfiguration.getTempFilesDir() + uuid + ".wav";
            AudioSystem.write(combinedAudioInputStream, AudioFileFormat.Type.WAVE, new File(filePath));
            return filePath;

        } catch (UnsupportedAudioFileException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
